package cn.jingyuan.bee.utils.codec;

import cn.jingyuan.bee.utils.CharsetUtils;
import cn.jingyuan.bee.utils.StringUtils;
import cn.jingyuan.bee.utils.io.FileUtils;
import cn.jingyuan.bee.utils.io.IoUtils;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * Base62 工具类，提供 Base62 的编码和解码方案
 */
public class Base62 {

    private static final Charset DEFAULT_CHARSET = CharsetUtils.CHARSET_UTF_8;

    private static final Base62Codec CODEC = Base62Codec.createGmp();

    /**
     * Base62 编码
     *
     * @param source 被编码的 Base62 字符串
     *
     * @return 被加密后的字符串
     */
    public static String encode(CharSequence source) {
        return encode(source, DEFAULT_CHARSET);
    }

    /**
     * Base62 编码
     *
     * @param source 被编码的 Base62 字符串
     * @param charset 字符集
     *
     * @return 被加密后的字符串
     */
    public static String encode(CharSequence source, Charset charset) {
        return encode(StringUtils.bytes(source, charset));
    }

    /**
     * Base62 编码
     *
     * @param source 被编码的 Base62 字符串
     *
     * @return 被加密后的字符串
     */
    public static String encode(byte[] source) {
        return new String(CODEC.encode(source));
    }

    /**
     * Base62 编码
     *
     * @param in 被编码 Base62 的流（一般为图片流或者文件流）
     *
     * @return 被加密后的字符串
     */
    public static String encode(InputStream in) {
        return encode(IoUtils.readBytes(in));
    }

    /**
     * Base62 编码
     *
     * @param file 被编码 Base62 的文件
     *
     * @return 被加密后的字符串
     */
    public static String encode(File file) {
        return encode(FileUtils.readBytes(file));
    }

    /**
     * Base62 解码
     *
     * @param source 被解码的 Base62 字符串
     *
     * @return 被加密后的字符串
     */
    public static String decodeStringGbk(CharSequence source) {
        return decodeString(source, CharsetUtils.CHARSET_GBK);
    }

    /**
     * Base62 解码
     *
     * @param source 被解码的 Base62 字符串
     *
     * @return 被加密后的字符串
     */
    public static String decodeString(CharSequence source) {
        return decodeString(source, DEFAULT_CHARSET);
    }

    /**
     * Base62 解码
     *
     * @param source 被解码的 Base62 字符串
     * @param charset 字符集
     *
     * @return 被加密后的字符串
     */
    public static String decodeString(CharSequence source, Charset charset) {
        return StringUtils.string(decode(source), charset);
    }

    /**
     * Base62 解码
     *
     * @param base62 被解码的 Base62 字符串
     * @param destFile 目标文件
     *
     * @return 目标文件
     */
    public static File decodeToFile(CharSequence base62, File destFile) {
        return FileUtils.writeBytes(decode(base62), destFile);
    }

    /**
     * Base62 解码
     *
     * @param base62Str 被解码的 Base62 字符串
     * @param out 写出到的流
     * @param isCloseOut 是否关闭输出流
     */
    public static void decodeToStream(CharSequence base62Str, OutputStream out, boolean isCloseOut) {
        IoUtils.write(out, isCloseOut, decode(base62Str));
    }

    /**
     * Base62 解码
     *
     * @param base62Str 被解码的 Base62 字符串
     *
     * @return 被加密后的字符串
     */
    public static byte[] decode(CharSequence base62Str) {
        return decode(StringUtils.bytes(base62Str, DEFAULT_CHARSET));
    }

    /**
     * 解码 Base62
     *
     * @param base62bytes Base62 输入
     *
     * @return 解码后的 bytes
     */
    public static byte[] decode(byte[] base62bytes) {
        return CODEC.decode(base62bytes);
    }

}
